﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.SqlClient;
using System.Configuration;

namespace TCC_Hotel.Repositorio
{
    public class ControleBancoDados
    {
        /// <summary>
        /// Armazena no banco de dados secundario o comando sql que o principal nao recebeu
        /// </summary>
        /// <param name="sql">Comando sql</param>
        public void EscreverComandoPerdido(string sql_perdido)
        {
            //pega a conectionstring do banco local
            SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["AplicacaoLocal"].ConnectionString);
            
            string sql = "INSERT INTO Comandos VALUES (@SQL)";
            SqlCommand comando_armazena = new SqlCommand(sql, con);

            //Adicionando o valor dos textBox nos parametros do comando
            comando_armazena.Parameters.Add(new SqlParameter("SQL", sql_perdido));

            try
            {
                //abre a conexao
                con.Open();
                //executa o comando com os parametros que foram adicionados acima
                comando_armazena.ExecuteNonQuery();
                //fecha a conexao
                con.Close();
            }
            catch(Exception e)
            {
                
            }
        }

        /// <summary>
        /// Armazena no banco de dados secundario o comando sql que o principal nao recebeu
        /// </summary>
        /// <param name="sql">Comando sql</param>
        public void EscreverComandoPerdidoServidor(string sql_perdido)
        {
            //pega a conectionstring do banco local
            SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["AplicacaoServidor"].ConnectionString);

            string sql = "INSERT INTO Comandos VALUES (@SQL)";
            SqlCommand comando_armazena = new SqlCommand(sql, con);

            //Adicionando o valor dos textBox nos parametros do comando
            comando_armazena.Parameters.Add(new SqlParameter("SQL", sql_perdido));

            try
            {
                //abre a conexao
                con.Open();
                //executa o comando com os parametros que foram adicionados acima
                comando_armazena.ExecuteNonQuery();
                //fecha a conexao
                con.Close();
            }
            catch (Exception e)
            {

            }
        }

        /// <summary>
        /// Verifica se há comandos não executados no banco principal. Se houver executa-os.
        /// </summary>
        public void verificaConsistencia()
        {
            //pega o connectionstring do web config
            SqlConnection con2 = new SqlConnection(ConfigurationManager.ConnectionStrings["AplicacaoLocal"].ConnectionString);

            List<string> listaPerdida = new List<string>();

            SqlDataReader reader = null;

            //monta a query
            string query = "SELECT Comandos FROM Comandos order by ID";
            SqlCommand cmd = new SqlCommand(query, con2);
            
                    
            try
            {
                //abre conexao
                con2.Open();

                //executa a query
                reader = cmd.ExecuteReader();

                //le os dados retornados
                while (reader.Read())
                {
                   listaPerdida.Add(Convert.ToString(reader["Comandos"]));
                }

                //fecha conexao
                con2.Close();
            }
            catch (Exception e)
            {

            }

            //Verifica se houve comandos perdidos
            if (listaPerdida.Count > 0)
            {
                SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["AplicacaoServidor"].ConnectionString);
           
                cmd.Connection = con;
                //abre a conexao
                con.Open();
                
                //Executa os comandos que foram perdidos enquanto oservidor estava inacessivel
                foreach(var item in listaPerdida)
                {
                    cmd.CommandText = item;
                    try
                    {
                        cmd.ExecuteNonQuery();
                    }
                    catch (SqlException e)
                    {

                    }
                }

                //fecha a conexao
                con.Close();  


//---------------------Remove todos os campos de comandos do banco secundario---------------------
                cmd.Connection = con2;
                string query_remover = "DELETE FROM Comandos";
                cmd.CommandText = query_remover;
                con2.Open();
                cmd.ExecuteNonQuery();
                //fecha a conexao
                con2.Close();
                

            }

        }

        /// <summary>
        /// Verifica se há comandos não executados no banco local. Se houver executa-os.
        /// </summary>
        public void verificaConsistenciaLocal()
        {
            //pega o connectionstring do web config
            SqlConnection con2 = new SqlConnection(ConfigurationManager.ConnectionStrings["AplicacaoServidor"].ConnectionString);

            List<string> listaPerdida = new List<string>();

            SqlDataReader reader = null;

            //monta a query
            string query = "SELECT Comandos FROM Comandos order by ID";
            SqlCommand cmd = new SqlCommand(query, con2);


            try
            {
                //abre conexao
                con2.Open();

                //executa a query
                reader = cmd.ExecuteReader();

                //le os dados retornados
                while (reader.Read())
                {
                    listaPerdida.Add(Convert.ToString(reader["Comandos"]));
                }

                //fecha conexao
                con2.Close();
            }
            catch (Exception e)
            {

            }

            //Verifica se houve comandos perdidos
            if (listaPerdida.Count > 0)
            {
                SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["AplicacaoLocal"].ConnectionString);

                cmd.Connection = con;

                try
                {
                    //abre a conexao
                    con.Open();

                    //Executa os comandos que foram perdidos enquanto oservidor estava inacessivel
                    foreach (var item in listaPerdida)
                    {
                        cmd.CommandText = item;
                        try
                        {
                            cmd.ExecuteNonQuery();
                        }
                        catch (SqlException e)
                        {

                        }
                    }

                    //fecha a conexao
                    con.Close();
                

                //---------------------Remove todos os campos de comandos do banco secundario---------------------
                    cmd.Connection = con2;
                    string query_remover = "DELETE FROM Comandos";
                    cmd.CommandText = query_remover;
                    con2.Open();
                    cmd.ExecuteNonQuery();
                    //fecha a conexao
                    con2.Close();
                }
                catch (Exception e)
                {

                }

            }

        }


        /// <summary>
        /// Escreve um comando SQL nos bancos de dados
        /// </summary>
        /// <param name="sql">Comando sql</param>
        /// <returns>Se foi inserido/editado com sucesso ou não</returns>
        public bool EscreveBancoDados(string sql)
        {

            //configura a conexao com ambos os bancos
            SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["AplicacaoServidor"].ConnectionString);
            SqlConnection con2 = new SqlConnection(ConfigurationManager.ConnectionStrings["AplicacaoLocal"].ConnectionString);
        
            //Cria uma objeto do tipo comando passando como parametro a string sql e a string de conexão
            SqlCommand comando = new SqlCommand(sql, con);



            
            //-----------------------------insere no servidor principal externo ------------------------------------------------
            try
            {

                //abre a conexao
                con.Open();

                //Verifica se tem algum comando nao executado no servidor principal
                verificaConsistencia();

                //executa o comando com os parametros que foram adicionados acima
                comando.ExecuteNonQuery();
                //fecha a conexao
                con.Close();

            }
            //não foi possivel abrir a conexao
            catch (SqlException e)
            {

                //erro referente a servidor inacessivel ou timeout ocorreu
                if (e.Number == 53 || e.Number == -2 || e.Number == 2)
                {
                    EscreverComandoPerdido(sql);
                }
                // já existe
                else
                {
                    return false;
                }
            }
            finally
            {
                con.Close();
            }


            //-----------------------------insere no servidor secundario local ------------------------------------------------
            try
            {
                comando.Connection = con2;
                //abre a conexao
                con2.Open();

                verificaConsistenciaLocal();

                //executa o comando com os parametros que foram adicionados acima
                comando.ExecuteNonQuery();
                //fecha a conexao
                con2.Close();
            }
            catch (SqlException e)
            {
                //erro referente a servidor inacessivel ou timeout ocorreu
                if (e.Number == 53 || e.Number == -2 || e.Number == 2)
                {
                    EscreverComandoPerdidoServidor(sql);
                }
                // já existe
                else
                {
                    return false;
                }
            }
            finally
            {
                con2.Close();
            }

            return true;

        }

    }
}